package com.myjava.utils;


import com.google.common.collect.Lists;
import com.myjava.annotation.ExcelExpField;
import com.myjava.inf.ExcelExportable;
import com.xiaoleilu.hutool.date.DateTime;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.util.Date;
import java.util.List;

/**
 * 基于自定义注解@ExcelExpField 的 excel导出工具类
 *
 * @Project: datacenter-parent
 * @Author: chendongliang
 * @Date: 2018/8/24 10:01
 */
public class ExcelUtils2 {

    private static final Logger logger = LoggerFactory.getLogger(ExcelUtils.class);

    private XSSFWorkbook workBook;
    private Sheet sheet;
    private List<ExcelField> excelFields;

    public ExcelUtils2(String sheetName) {
        logger.debug("--------------------------------excel导出工具初始化-------------------------------------");
        workBook = new XSSFWorkbook();
        sheet = workBook.createSheet(sheetName);
    }

    public Workbook writeExcel(List<? extends ExcelExportable> data) {
        logger.debug("--------------------------------excel导出-------------------------------------");
        if (data == null || data.size() == 0) {
            return null;
        }
        Field[] fields = data.get(0).getClass().getDeclaredFields();
        //所有要导出的字段
        excelFields = Lists.newArrayList();
        for (Field field : fields) {
            if (field.isAnnotationPresent(ExcelExpField.class)) {
                String fieldName = field.getName();
                String title = field.getAnnotation(ExcelExpField.class).title();
                Integer colIndex = field.getAnnotation(ExcelExpField.class).colIndex();
                String formatter = field.getAnnotation(ExcelExpField.class).formatter();
                excelFields.add(new ExcelField(fieldName, title, colIndex, formatter));
            }
        }
        if (excelFields.size() == 0) {
            return null;
        }
        //写入标题行
        writeTitle(excelFields, workBook);
        //写入数据行
        writeData(data);
        //生成文件
        return workBook;
    }

    private void writeData(List<? extends ExcelExportable> data) {
        logger.debug("--------------------------------excel导出内容写入--------------------------------");
        //行索引，除去标题行，从第二行开始
        int rowNum = 1;
        //轮询数据
        for (ExcelExportable d : data) {
            //创建行
            Row row = sheet.createRow(rowNum);
            //轮询导出列
            for (ExcelField f : excelFields) {
                try {
                    Field field = d.getClass().getDeclaredField(f.getName());
                    field.setAccessible(true);
                    Object value = field.get(d);
                    //写入单元格内容
                    if (value instanceof Date && f.formatter != null) {  //日期格式处理
                        String v = DateTime.of((Date) value).toString(f.formatter);
                        writeRow(row, f.getColIndex(), v);
                    } else {
                        writeRow(row, f.getColIndex(), value);
                    }
                } catch (Exception e) {
                    logger.debug("*******************************excel导出写入内容异常***************************");
                }
            }
            rowNum++;
        }
    }

    /***
     * 写入标题行
     * @param titles
     */
    private void writeTitle(List<ExcelField> titles, XSSFWorkbook hssfWorkbook) {
        logger.debug("--------------------------------excel导出标题行写入--------------------------------");
        XSSFFont headerFont = hssfWorkbook.createFont();
        headerFont.setColor(Font.COLOR_NORMAL);
        headerFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        XSSFCellStyle hssfCellStyle = hssfWorkbook.createCellStyle();
        hssfCellStyle.setFont(headerFont);
        Row row = sheet.createRow(0);
        titles.forEach(excelField -> {
            Cell cell = row.createCell(excelField.colIndex);
            cell.setCellValue(excelField.getTitle());
            cell.setCellStyle(hssfCellStyle);
        });
    }

    /***
     * 写入单元格内容
     * @param colNum
     * @param value
     */
    private void writeRow(Row row, int colNum, Object value) {
        Cell cell = row.createCell(colNum);
        cell.setCellValue(value.toString());
    }


    class ExcelField {
        String name;
        String title;
        Integer colIndex;
        String formatter;

        ExcelField(String name, String title, Integer colIndex, String format) {
            this.name = name;
            this.title = title;
            this.colIndex = colIndex;
            this.formatter = format;
        }

        public String getName() {
            return name;
        }

        public Integer getColIndex() {
            return colIndex;
        }

        public String getTitle() {
            return title;
        }

        public String getFormatter() {
            return formatter;
        }
    }

    public static void main(String[] args) {

    }

}
